/*
 *  This file is part of Cha++ers.
 *
 *  Cha++ers is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Cha++ers is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Cha++ers.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "libchatters.h"
#include "socket.h"
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include "src/libraries/text.h"
#include "src/defined.h"

T_Socket* conn;

void Disconnect()
{
	if (conn) {
		conn->Disconnect();
	}
}

void SendMessage(std::string sdata)
{
	if (sdata[0] == '/')conn->Send(sdata.substr(1).append("\n").c_str());
	else conn->Send(sdata.insert(0,">  ").append("\n"));
}

void SendMessage(const char* sdata)
{
	std::string fdata(sdata);
	SendMessage(fdata);
}

void * Command_Login(void * args)
{
	targs data;
	ReadConfig(&data,"config.txt");
	if (!data.username.size()||!data.userpass.size())return NULL;
	std::string username = data.username;
	std::string userpass = data.userpass;
	username = username.insert(0,"login ").append("\n");
	userpass = userpass.append("\n");
	conn->Wait(1);
	conn->Send("telnettype 1\n");
	conn->Send(username.c_str());
	conn->Send(userpass.c_str());
	return NULL;
}

static void Command_Who(std::string data)
{
	ClearUserlist();
	std::string curuser = "";
	size_t nl;
	nl = data.find(",");
	while (nl != std::string::npos) {
		curuser = data.substr(0,nl);
		data = data.erase(0,nl+1);
		while (curuser.find("+") != std::string::npos)curuser.replace(curuser.find("+"),1," ");
		if (curuser.find("~") != std::string::npos)curuser.replace(curuser.find("~"),1,"[AWAY]");
		AppendUserlist(curuser);
		nl = data.find(",");
	}
	while (data.find("+") != std::string::npos)data.replace(data.find("+"),1," ");
	if (data.find("~") != std::string::npos)data.replace(data.find("~"),1,"[AWAY]");
	AppendUserlist(data);
}

static void Do_Command(std::string data)
{
	size_t nl;
	nl = data.find(" ");
	if (data[0] != '.') {
		WriteLine(data.c_str());
	} else if (nl != std::string::npos) {
		if (data.substr(0,nl).compare(".who") == 0) {
			Command_Who(data.substr(nl+1));
		}
	}
}

static std::string Strip_Colors(std::string buf)
{
	std::string retval(buf);
	retval = replaceText(retval,"\033[37m","");
	retval = replaceText(retval,"\033[35m","");
	retval = replaceText(retval,"\033[34m","");
	retval = replaceText(retval,"\033[32m","");
	retval = replaceText(retval,"\033[31m","");
	retval = replaceText(retval,"\033[30m","");
	retval = replaceText(retval,"\033[24m","");
	retval = replaceText(retval,"\033[22m","");
	retval = replaceText(retval,"\033[4m","");
	retval = replaceText(retval,"\033[3m","");
	retval = replaceText(retval,"\033[1m","");
	retval = replaceText(retval,"\033[37;40m","");
	return retval;
}

static std::string Strip_ANSI(const char* buf)
{
	std::string retval(buf);
	retval = replaceText(retval,"\033[J","");
	retval = replaceText(retval,"\033[2J","");
	retval = replaceText(retval,"\x1f","");

	retval = replaceText(retval,"\r","");
	retval = replaceText(retval,"\b","");
	retval = replaceText(retval,"\n\n","\n");
	retval = stripBadChars(retval);
	return retval;
}

static void Interpret(char* bufdata,bool* normal_op)
{
	gdk_threads_enter();
	std::string funnel = Strip_ANSI(bufdata);
	std::string curline = "";

	char* buf = (char*)malloc(8192);
	strcpy(buf,funnel.c_str());
	char* pch = strtok(buf,"\n");
	std::string final("");
	if (pch != NULL) {
		final.assign(pch);

		if (*normal_op == false) {
			std::string test = Strip_Colors(final);
			if (strncmp("Quote of the Day:",test.c_str(),17)==0) {
				pthread_t pid;
				pthread_create(&pid,NULL,Command_Login,NULL);
				*normal_op = true;
			}
		} else if (pch[0] == '.') {
			final.clear();
			Do_Command(pch);

		} else if (pch[0] == 1) {
			final.clear();
			Do_Command(pch+1);
		}
	}
	while (pch != NULL) {
		pch = strtok(NULL,"\n");

		if (pch == NULL) {
			final = Strip_Colors(final);
			WriteLine(final.c_str());
			TextView_ScrollToBottom();
			final.clear();
			break;

		}

		if (*normal_op == false) {
			std::string test = Strip_Colors(pch);
			if (strncmp("Quote of the Day:",test.c_str(),17)==0) {
				pthread_t pid;
				pthread_create(&pid,NULL,Command_Login,NULL);
				*normal_op = true;
			}
		}

		if (pch[0] == '\033'||pch[0] == '\t') {
			final = Strip_Colors(final);
			WriteLine(final.c_str());
			TextView_ScrollToBottom();
			final.clear();
			final.assign(pch);

		} else if (pch[0] == '.') {
			final = Strip_Colors(final);
			WriteLine(final.c_str());
			TextView_ScrollToBottom();
			final.clear();
			Do_Command(pch);

		} else if (pch[0] == 1) {
			final = Strip_Colors(final);
			WriteLine(final.c_str());
			TextView_ScrollToBottom();
			final.clear();
			Do_Command(pch+1);

		} else {
			if (final[final.size()-1] != ' ')final.append(" ");
			final.append(pch);
		}

	}
	if (buf != NULL)free(buf);
	gdk_flush();
	gdk_threads_leave();
}

static void Connection_Loop(char* buf)
{
	bool normal_op = false;
	while (conn->Connected()) {
		memset(buf,'\0',BUFSIZE);
		conn->Receive(buf);
		if (strlen(buf)) {

			while (buf[strlen(buf)-1] != '\n'&&strncmp(buf+3,"Please enter your telnet password:",34) != 0) {
				char* temp = (char*)malloc(8192);
				memset(temp,'\0',8192);
				conn->Receive(temp);
				strcat(buf,temp);
				if (temp != NULL)free(temp);
			}

			Interpret(buf,&normal_op);
		}
	}
	gdk_threads_enter();
	WriteLine("( Disconnected )");
	gdk_flush();
	gdk_threads_leave();
}


void *Init_Session(void * args)
{
	T_Socket conn_mgr;
	char buf[BUFSIZE];
	if (conn_mgr.Connected()) {
		WriteLine("You are already connected, moron.");
		TextView_ScrollToBottom();
		pthread_exit(0);
		return NULL;
	}

	/*Retrieve the data needed to connect to the server*/

	targs data;
	ReadConfig(&data,"config.txt");
	std::string passwd(data.telnetpass);
	passwd.append("\n");
	/*If the connection fails, clean up and reset the button label back to "Connect"*/
	if (!conn_mgr.Connect()) {
		WriteLine("Connection Failed");
		TextView_ScrollToBottom();
		pthread_exit(0);
		return NULL;
	}

	/*Activate the connection by sending a standard newline*/
	conn_mgr.Send("\n");

	/*Send the telnet password to the server*/
	conn_mgr.Send(passwd.c_str());
	conn = &conn_mgr;
	Connection_Loop(buf);
	return NULL;
}
